Areas

Declared in: <kernel/OS.h>


Overview

An area is a chunk of virtual memory. As such, it has all the expected properties of virtual memory: It has a starting address, a size, the locations that comprise it are contiguous, and it maps to (possibly non-contiguous) physical memory. The primary differences between an area and "standard" virtual memory (memory that you allocate through malloc(), for example) are these:

Because areas are large--4096 bytes minimum--you don't create them arbitrarily. The two most compelling reasons to create an area are the two first points listed above: To share data among different applications, and to lock memory into RAM.


Identifying an Area

An area is uniquely identified (system-wide) by its area_id number. The area_id is assigned automatically by create_area(), a function that does what it says. Most of the other area functions require an area_id argument.

When you create an area, you get to name it. Area names are not unique--any number of areas can be assigned the same name.


Sharing Areas

If you want to share an area with another application, you can broadcast the area's area_id number, but it's recommended that, instead, you publish the area's name. Given an area name, a "remote" application can retrieve the area's ID number by calling find_area().

To use an area that was created by another application, the first thing you should do, having acquired the area's area_id through find_area(), is "clone" the area. You do this by calling the clone_area() function. The function returns a new area_id number that identifies your clone of the original area. All further references to the area should be based on the ID of the clone.

The physical memory that lies beneath a cloned area is never implicitly copied--for example, the area mechanism doesn't perform a "copy-on-write". If two areas (more specifically, two area_id numbers) refer to the same memory because of cloning, a data modification that's affected through one area will be seen by the other area.

Note: Because names aren't unique, multiple calls to find_area() with the same name won't all necessarily return the same area_id--consider the case where more than one instantiation of the same area-creating application is running on your computer.


Locking an Area

When you're working with moderately large amounts of data, it's often the case that you would prefer that the data remain in RAM, even if the rest of your application needs to be swapped out. An argument to create_area() lets you declare, through the use of one of the following constants, the locking scheme that you wish to apply to your area:

Keep in mind that locking an area essentially reduces the amount of RAM that can be used by other applications, and so increases the likelihood of swapping. So you shouldn't lock simply because you're greedy. But if the area that you're locking is going to be shared among some number of other applications, or if you're writing a real-time application that processes large chunks of data, then locking can be a benefit.

The locking scheme is set by the create_area() function and is thereafter immutable. You can't re-declare the lock when you clone an area.


Using an Area

Ultimately, you use an area for the virtual memory that it represents: You create an area because you want some memory to which you can write and from which you can read data. These acts are performed in the usual manner, through references to specific addresses. Setting a pointer to a location within the area, and checking that you haven't exceeded the area's memory bounds as you increment the pointer (while reading or writing) are your own responsibility. To do this properly, you need to know the area's starting address and its extent:

An important point, with regard to area_info, is that the address field is only valid for the application that created or cloned the area (in other words, that created the area_id that was passed to get_area_info()). Although the memory that underlies an area is global, the address that you get from an area_info structure refers to a specific address space.

If there's any question about whether a particular area_id is "local" or "foreign," you can compare the area_info.team field to your thread's team.


Deleting an Area

When your application quits, the areas (the area_id numbers) that it created through create_area() or clone_area() are automatically rendered invalid. The memory underlying these areas, however, isn't necessarily freed. An area's memory is freed only when (and as soon as) there are no more areas that refer to it.

You can force the invalidation of an area_id by passing it to the delete_area() function. Again, the underlying memory is only freed if yours is the last area to refer to the memory.

Deleting an area, whether explicitly through delete_area(), or because your application quit, never affects the status of other areas that were cloned from it.


Functions


area_for()

      area_id area_for(void *addr)

Returns the area_id of the area that contains the given address (within your own team's address space). The argument needn't be the starting address of an area, nor must it start on a page boundary. If it lies anywhere within an area, the ID of that area is returned.

Since the address is taken to be in the local address space, the area that's returned will also be local--it will have been created or cloned by your application.

If the address doesn't lie within an area, B_ERROR is returned.

See also: find_area()


clone_area()

      long clone_area(const char *clone_name, 
         void **clone_addr,
         ulong clone_addr_spec, 
         ulong clone_protection,
         area_id source_area)

Creates a new area (the clone area) that maps to the same physical memory as an existing area (the source area). The arguments are:

The cloned area inherits the source area's locking scheme (B_FULL_LOCK, B_LAZY_LOCK, or B_NO_LOCK).

Usually, the source area and clone area are in two different applications. It's possible to clone an area from a source that's in the same application, but there's not much reason to do so unless you want the areas to have different protections.

If area_clone() clone is successful, the clone's area_id is returned. Otherwise, the function returns one of the following error constants:

Constant Meaning
B_BAD_VALUE Bad argument value; you passed an unrecognized constant for addr_spec or lock, the addr value isn't a multiple of B_PAGE_SIZE, you set addr_spec to B_EXACT_ADDRESS or B_CLONE_ADDRESS but the address request couldn't be fulfilled, or source_area doesn't identify an existing area.
B_NO_MEMORY Not enough memory to allocate the system structures that support this area.
B_ERROR Some other system error prevented the area from being created.

See also: create_area(), delete_area()


create_area()

      area_id create_area(const char *name,
         void **addr,
         ulong addr_spec,
         long size,
         ulong lock,
         ulong protection)

Creates a new area and returns its area_id. The arguments are:

      /* Set the address to a page boundary. */
      char *addr = (char *)(4096 * 100);
      
      /* Pass the address of addr as the second argument. */
      create_area( "my area", &addr, ...);

The function sets the value of *addr to the area's actual starting address--it may be different from the one you requested. The constancy of *addr depends on the value of addr_spec, as explained next.

If create_area() is successful, the new area_id number is returned. If it's unsuccessful, one of the following error constants is returned:

Constant Meaning
B_BAD_VALUE Bad argument value. You passed an unrecognized constant for addr_spec or lock, the addr or size value isn't a multiple of B_PAGE_SIZE, or you set addr_spec to B_EXACT_ADDRESS but the address request couldn't be fulfilled.
B_NO_MEMORY Not enough memory to allocate the necessary system structures that support this area. Note that this error code doesn't mean that you asked for too much physical memory.
B_ERROR Some other system error prevented the area from being created. Most notably, B_ERROR is returned if size is too large.

See also: clone_area(), delete_area()


delete_area()

      long delete_area(area_id area)

Deletes the designated area. If no one other area maps to the physical memory that this area represents, the memory is freed.

Note: Currently, anybody can delete any area--the act isn't denied if, for example, the area_id argument was created by another application. This freedom will be rescinded in a later release. Until then, try to avoid deleting other application's areas.

If area doesn't designate an actual area, this function returns B_ERROR; otherwise it returns B_NO_ERROR.

See also: create_area(), clone_area()


find_area()

      area_id find_area(const char *name)

Returns an area that has a name that matches the argument. Area names needn't be unique--successive calls to this function with the same argument value may not return the same area_id.

What you do with the area you've found depends on where it came from:

If the argument doesn't identify an existing area, the B_NAME_NOT_FOUND error code is returned.

See also: area_for()


get_area_info(), get_nth_area_info()

      long get_area_info(area_id area, area_info *info)
      long get_nth_area_info(team_id team, long n, area_info *info)

Copies information about a particular area into the area_info structure designated by info. The first version of the function designates the area directly, by area_id. The second version designates the n'th area within the given team. If the team argument is 0, all teams are considered.

The area_info structure is defined as:

      typedef struct area_info {
            area_id  area;
            char  name[B_OS_NAME_LENGTH];
            void  *address;
            long  size;
            ulong  lock;
            ulong  protection;
            team_id  team;
            long  ram_size;
            long  copy_count;
            long  in_count;
            long  out_count;
         } area_info;

The fields are:

The final four fields give information about the area that's useful in diagnosing system use. The fields are particularly valuable if you're hunting for memory leaks:

If the area argument doesn't identify an existing area, the function returns B_BAD_VALUE; otherwise it returns B_NO_ERROR.


resize_area()

      long resize_area(area_id area, long new_size)

Sets the size of the designated area to new_size, measured in bytes. The new_size argument must be a multiple of B_PAGE_SIZE (4096).

Size modifications affect the end of the area's existing memory allocation: If you're increasing the size of the area, the new memory is added to the end of area; if you're shrinking the area, end pages are released and freed. In neither case does the area's starting address change, nor is existing data modified (expect, of course, for data that's lost due to shrinkage).

If the function is successful, B_NO_ERROR is returned. Otherwise one of the following error codes is returned:

Constant Meaning
B_BAD_VALUE Either area doesn't signify a valid area, or new_size isn't a multiple of B_PAGE_SIZE.
B_NO_MEMORY Not enough memory to allocate the system structures that support the new portion of the area. This should only happen if you're increasing the size of the area. Note that this error code doesn't mean that you asked for too much physical memory.
B_ERROR Some other system error prevented the area from being created. Most notably, B_ERROR is returned if new_size is too large.

See also: create_area()


set_area_protection()

      long set_area_protection(area_id area, ulong new_protection)

Sets the given area's read and write protection. The new_protection argument is a mask that specifies one or both of the values B_READ_AREA and B_WRITE_AREA. The former means that the area can be read; the latter, that it can be written to. An area's protection only applies to access to the underlying memory through that specific area. Different area clones that refer to the same memory may have different protections.

The function fails (the old protection isn't changed) and returns B_BAD_VALUE if area doesn't identify a valid area; otherwise it returns B_NO_ERROR.

See also: create_area()




The Be Book, HTML Edition, for Release 1.1d7 of the Be OS.

Copyright © 1996 Be, Inc. All rights reserved.

Be, the Be logo, BeBox, Be OS, Be Operating System, and GeekPort are trademarks of Be, Inc.

Last modified April 29, 1996.